home *** CD-ROM | disk | FTP | other *** search
Text File | 1999-01-11 | 9.6 KB | 299 lines | [TEXT/CWIE] |
- // SpritePersistence.c
- // -------------------
- // v2.3
- // (Note: uses DataPersistence services)
- // feedback: macdev@tnuctip.com
-
- #include "SWIncludes.h"
-
- #include "DataPersistence.h"
-
- #define OWNER
- #include "SpritePersistence.h"
- #undef OWNER
-
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // THESE ROUTINES MAY BE MODIFIED TO ADAPT TO YOUR OWN DATA
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •————Customizable————
-
-
- ///--------------------------------------------------------------------------------------
- // This is called before writing a record to disk. You just have to fill the record.
- ///--------------------------------------------------------------------------------------
-
- void SWGCopyFromSpriteToRecord (SpritePtr spriteP, tSpriteSaveHandle recordHandle)
- {
- (*recordHandle)->hz = spriteP->destFrameRect.left;
- (*recordHandle)->vt = spriteP->destFrameRect.top;
- (*recordHandle)->userDataExample = spriteP->userData;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // This is called after reading a record from disk. You update the sprite using the data.
- // Don't forget to call the appropriate SW routines to update the sprites' position,
- // deltas, whatever you have changed.
- ///--------------------------------------------------------------------------------------
-
- void SWGCopyFromRecordToSprite (tSpriteSaveHandle recordHandle, SpritePtr spriteP)
- {
- SWMoveSprite (spriteP, (*recordHandle)->hz, (*recordHandle)->vt);
- spriteP->userData = (*recordHandle)->userDataExample;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // This is where the resource ID for each sprite is computed. It is placed in the <customizable
- // routines> section because you might want a different numbering scheme (e.g. you might want
- // several copies of the same sprites, at different times, or whatever..) That's also
- // why spriteP is provided: you might want to use it's data in your numbering scheme.
- ///--------------------------------------------------------------------------------------
-
- SInt16 SWGComputeResourceID (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
- {
- #pragma unused (spriteP)
-
- return layerNum * kMaxSpritesInOneLayer + spriteNum;
- }
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // PUBLIC : called by your app
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •—————Public—————
-
- ///--------------------------------------------------------------------------------------
- // All layers in the world will be scanned and written out or read in.
- // File is automatically opened and then closed (if user hasn't opened it before calling).
- //
- // There are interface macros for Save and Load (look inside SpritePersistence.h) :
- // #define SWGSaveSpritesInAllLayers(x) SWGDoSpritesInAllLayers (x, true)
- // #define SWGLoadSpritesInAllLayers(x) SWGDoSpritesInAllLayers (x, false)
- // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGDoSpritesInAllLayers (SpriteWorldPtr spriteWorldP, Boolean write)
- {
- OSErr err;
- SpriteLayerPtr spriteLayerP;
- Boolean fileWasOpenedHere;
-
- fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
-
- spriteLayerP = spriteWorldP->headSpriteLayerP;
-
- while (spriteLayerP != nil)
- {
- err = SWGDoSpritesInLayer (spriteLayerP, write);
- if (err != noErr)
- break;
-
- spriteLayerP = spriteLayerP->nextSpriteLayerP;
- }
-
- if (fileWasOpenedHere)
- SWGClosePersistenceFile ();
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // All sprites in this layer will be scanned and written out or read in, through a hook to
- // SWGCopyFromSpriteToRecord or SWGCopyFromRecordToSprite.
- // The file is automatically opened and then closed (if user hasn't opened it before calling).
- //
- // There are interface macros for Save and Load (look inside SpritePersistence.h) :
- // #define SWGSaveSpritesInLayer(x) SWGDoSpritesInLayer (x, true)
- // #define SWGLoadSpritesInLayer(x) SWGDoSpritesInLayer (x, false)
- // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGDoSpritesInLayer (SpriteLayerPtr spriteLayerP, Boolean write)
- {
- SInt16 layerNum;
- SInt16 spriteNum = 0;
- OSErr err;
- SpritePtr curSpriteP = nil;
- Boolean fileWasOpenedHere;
-
- fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
-
- layerNum = SWGGetLayerNumber (spriteLayerP);
-
- while ((curSpriteP = SWGetNextSprite (spriteLayerP, curSpriteP)) != nil)
- {
- spriteNum++; // numbered [1..x]
- err = SWGDoSingleSprite (layerNum, spriteNum, curSpriteP, write);
- if (err != noErr)
- break;
- }
-
- if (fileWasOpenedHere)
- SWGClosePersistenceFile ();
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Single sprite read/write.
- //
- // There are interface macros for Save and Load (look inside SpritePersistence.h) :
- // #define SWGSaveSingleSprite (x,y,z) SWGDoSingleSprite (x, y, z, true)
- // #define SWGLoadSingleSprite (x,y,z) SWGDoSingleSprite (x, y, z, false)
- // This simple trick makes SpritePersistence's code size smaller at virtually no cost.
- ///--------------------------------------------------------------------------------------
-
- OSErr SWGDoSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP, Boolean write)
- {
- OSErr err;
- Boolean fileWasOpenedHere;
-
- fileWasOpenedHere = SWGOpenPersistenceFileConditionally (kSpriteSaveRezType);
-
- if (write)
- err = _SWGSaveSingleSprite (layerNum, spriteNum, spriteP);
- else
- err = _SWGLoadSingleSprite (layerNum, spriteNum, spriteP);
-
- if (fileWasOpenedHere)
- SWGClosePersistenceFile ();
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Return a logical number in [1..x] based on layer ordering.
- // Quickly scans the layer links, counting the number of steps needed to
- // reach the head of list.
- ///--------------------------------------------------------------------------------------
-
- SInt16 SWGGetLayerNumber (SpriteLayerPtr spriteLayerP)
- {
- SInt16 num = 0;
-
- do
- {
- num++;
- spriteLayerP = spriteLayerP->prevSpriteLayerP;
- }
- while (spriteLayerP != nil);
-
-
- return num;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Return a logical number in [1..x] based on sprite ordering.
- // Quickly scans the sprite links, counting the number of steps needed to
- // reach the head of list.
- ///--------------------------------------------------------------------------------------
-
- SInt16 SWGGetSpriteNumber (SpritePtr spriteP)
- {
- SInt16 num = 0;
-
- do
- {
- num++;
- spriteP = spriteP->prevSpriteP;
- }
- while (spriteP != nil);
-
-
- return num;
- }
-
-
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
- // PRIVATE : internal use only
- // ©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©©
-
- #pragma mark •—————Private—————
-
- ///--------------------------------------------------------------------------------------
- // Does the actual saving job for a sprite
- ///--------------------------------------------------------------------------------------
-
- OSErr _SWGSaveSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
- {
- OSErr err = noErr;
-
- if (gSWGBufferHandle == nil)
- {
- err = _SWGCreateBufferHandle ();
- if (gSWGBufferHandle == nil) // allocation failed, abort operation
- return err;
- }
-
- // #MOD?
- // Read the rez before writing (if not found, create it with zeroed data);
- // this allows the SWGCopyFromSpriteToRecord routine to replace data partially,
- // if the user so wishes.
-
- HLock (gSWGBufferHandle);
- SWGCopyFromSpriteToRecord (spriteP, (tSpriteSaveHandle) gSWGBufferHandle);
- err = SWGSaveRecord (*gSWGBufferHandle, sizeof (tSpriteSaveRec), SWGComputeResourceID (layerNum, spriteNum, spriteP));
- HUnlock (gSWGBufferHandle);
-
- return err;
- }
-
-
-
- ///--------------------------------------------------------------------------------------
- // Does the actual loading job for a sprite
- ///--------------------------------------------------------------------------------------
-
- OSErr _SWGLoadSingleSprite (SInt16 layerNum, SInt16 spriteNum, SpritePtr spriteP)
- {
- OSErr err = noErr;
-
- if (gSWGBufferHandle == nil)
- {
- err = _SWGCreateBufferHandle ();
- if (gSWGBufferHandle == nil) // allocation failed, abort operation
- return err;
- }
-
- HLock (gSWGBufferHandle);
-
- err = SWGLoadRecord (*gSWGBufferHandle, sizeof (tSpriteSaveRec), SWGComputeResourceID (layerNum, spriteNum, spriteP));
-
- if (err == noErr || err == kDataSizeSmallerError || err == kDataSizeBiggerError) // accept different size
- SWGCopyFromRecordToSprite ((tSpriteSaveHandle) gSWGBufferHandle, spriteP);
-
- HUnlock (gSWGBufferHandle);
-
- return err;
- }
-
-
- ///--------------------------------------------------------------------------------------
- // Allocate a single permanent handle to be used for all load/saves.
- ///--------------------------------------------------------------------------------------
-
- OSErr _SWGCreateBufferHandle (void)
- {
- OSErr err = noErr;
-
- gSWGBufferHandle = NewHandle (sizeof (tSpriteSaveRec));
- if (gSWGBufferHandle == nil)
- {
- err = memFullErr;
- SWGErrorReportingStub (err); // default is simply a beep
- }
-
- return err;
- }
-
- // end
-